package com.magenta.maxoptra.gis.postal;

import com.magenta.maxoptra.gis.DistanceMatrixKey;
import com.magenta.maxoptra.gis.GeoCountry;
import com.magenta.maxoptra.gis.PostalCode;

import java.io.Serializable;

/**
 * UK postal code ({@link com.magenta.maxoptra.gis.format.postal.PostalCodeFormatUK Format})
 *
 * @author Sergey Grachev
 */
public class PostalCodeUK implements PostalCode, Serializable {

    private static final long serialVersionUID = 6796670202287502144L;

    protected final boolean special;
    protected final String area;
    protected final String district;
    protected final String sector;
    protected final String unit;
    protected DistanceMatrixKey dmKey; // lazy init by request

    public PostalCodeUK(final String area, final String district, final String sector, final String unit, final boolean special) {
        this.area = area;
        this.district = district;
        this.sector = sector;
        this.unit = unit;
        this.special = special;
    }

    public String getArea() {
        return area;
    }

    public String getDistrict() {
        return district;
    }

    public String getSector() {
        return sector;
    }

    public String getUnit() {
        return unit;
    }

    public boolean isSpecial() {
        return special;
    }

    @Override
    public GeoCountry getCountry() {
        return GeoCountry.UK;
    }

    /**
     * Format:
     * <pre>
     *  AA991
     *  \__||
     *     |sector (optional)
     *     area and district (optional), always 4 chars
     * </pre>
     */
    @Override
    public DistanceMatrixKey getDistanceMatrixKey() {
    	if ( dmKey == null ) {
    		final String key = special ? area : String.format("%s %s", area + district, sector != null ? sector : "");
    		dmKey = new DistanceMatrixKey() {
                private static final long serialVersionUID = 4733583744688550330L;
				@Override
				public Object getValue() {
					return key;
				}
			};
    	}
    	return dmKey;
    }

    @Override
    public String toString() {
        return special ? area : area + district + (sector != null && unit != null ? ' ' + sector + unit : "");
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof PostalCodeUK)) return false;

        final PostalCodeUK that = (PostalCodeUK) o;

        if (special != that.special) return false;
        if (area != null ? !area.equals(that.area) : that.area != null) return false;
        if (district != null ? !district.equals(that.district) : that.district != null) return false;
        if (sector != null ? !sector.equals(that.sector) : that.sector != null) return false;
        if (unit != null ? !unit.equals(that.unit) : that.unit != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = (special ? 1 : 0);
        result = 31 * result + (area != null ? area.hashCode() : 0);
        result = 31 * result + (district != null ? district.hashCode() : 0);
        result = 31 * result + (sector != null ? sector.hashCode() : 0);
        result = 31 * result + (unit != null ? unit.hashCode() : 0);
        return result;
    }
}

